package org.dromara.system.utils;

import lombok.Data;
import lombok.Getter;

import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Objects;
import java.util.Properties;
import java.util.Random;

/**
 * @Description: 发送邮件工具类
 * @author: Gavino
 * @date: 2023年10月11日 14:29
 */
public class SendEmailUtils {

    //发送人邮箱账号
    public static String myEmailAccount = "dora@tradeoasis.shop";
    //邮箱密码不是登录密码，需要登录邮箱后台配置
    public static String myEmailPassword = "C67kfTpd";

    // 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
    // 网易126邮箱的 SMTP 服务器地址为: smtp.163.com
    public static String myEmailSMTPHost = "smtp-n.global-mail.cn";

    // 收件人邮箱（替换为自己知道的有效邮箱）
    public static String receiveMailAccount = "1947888082@qq.com";


    public static void main(String[] args) throws Exception {

        //设置邮件服务器配置
        EmailServerCfg cfg = new EmailServerCfg();
        cfg.setAccount(myEmailAccount);
        cfg.setPassword(myEmailPassword);
        cfg.setHost(myEmailSMTPHost);
        cfg.setPort("465");
        cfg.setProtocol("smtp");
        cfg.setEnableSsl(1);

        //构建邮件服务session
        Session session = SendEmailUtils.getSession(cfg);

        // 4. 根据 Session 获取邮件传输对象
        Transport transport;
        try {
            transport = session.getTransport();
            transport.connect(myEmailAccount, myEmailPassword);
            System.out.println("连接成功");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("根据 Session 获取邮件传输对象异常");
        }
    }

    /**
     * 创建一封只包含文本的简单邮件
     *
     * @param receiveMail 收件人邮箱
     * @param context     邮件内容
     */
    public static void sendMessageTest(String receiveMail, String context) throws Exception {
        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
        System.out.println("1. 创建参数配置, 用于连接邮件服务器的参数配置");
        Properties props = new Properties();                    // 参数配置
        props.setProperty("mail.transport.protocol", "smtp");   // 使用的协议（JavaMail规范要求）
        props.setProperty("mail.smtp.host", myEmailSMTPHost);   // 发件人的邮箱的 SMTP 服务器地址
        props.setProperty("mail.smtp.port", "25");  //主机端口号
        props.setProperty("mail.smtp.auth", "true");            // 需要请求认证

        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
        System.out.println("2. 根据配置创建会话对象, 用于和邮件服务器交互");
        Session session = Session.getInstance(props);
        // 设置为debug模式, 可以查看详细的发送 log
        System.out.println("设置为debug模式, 可以查看详细的发送 log");
        session.setDebug(true);
        // 1. 创建一封邮件
        System.out.println("1. 创建一封邮件");
        MimeMessage message = new MimeMessage(session);

        // 2. From: 发件人
        message.setFrom(new InternetAddress(myEmailAccount, myEmailAccount, "UTF-8"));

        // 3. To: 收件人（可以增加多个收件人、抄送、密送）
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, "XX用户", "UTF-8"));

        // 4. Subject: 邮件主题
        message.setSubject("主题", "UTF-8");

        // 5. Content: 邮件正文（可以使用html标签）
        message.setContent("动态码为：" + context, "text/html;charset=UTF-8");
        // 6. 设置发件时间
        message.setSentDate(new Date());

        // 7. 保存设置
        message.saveChanges();

        // 4. 根据 Session 获取邮件传输对象
        Transport transport = session.getTransport();
        transport.connect(myEmailAccount, myEmailPassword);

        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        // 7. 关闭连接
        transport.close();
    }

    /**
     * 创建邮件服务Session
     */
    public static Session getSession(EmailServerCfg cfg){
        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
        Properties props = new Properties();                    // 参数配置
        props.setProperty("mail.transport.protocol",cfg.getProtocol());   // 使用的协议（JavaMail规范要求）
        props.setProperty("mail.smtp.host", cfg.getHost());   // 发件人的邮箱的 SMTP 服务器地址
        props.setProperty("mail.smtp.port", cfg.getPort());  //主机端口号
        props.setProperty("mail.smtp.auth", "true");            // 需要请求认证
        props.setProperty("mail.smtp.ssl.enable", Objects.equals(cfg.getEnableSsl(), 1) ? "true" : "false"); // 启用 SSL

        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
        return Session.getInstance(props);
    }

    /**
     * 构建邮件
     *
     * @param cfg         cfg
     * @param session     session
     * @param receiveMail receiveMail
     * @param subject     subject
     * @param content     content
     * @return MimeMessage
     */
    public static MimeMessage buildMessage(EmailServerCfg cfg, Session session, String receiveMail,String subject, String content){
        MimeMessage message = null;

        try {
            // 1. 创建一封邮件
            message = new MimeMessage(session);

            // 2. From: 发件人
            message.setFrom(new InternetAddress(cfg.getAccount(), cfg.getAccount(), "UTF-8"));

            // 3. To: 收件人（可以增加多个收件人、抄送、密送）
            message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, receiveMail, "UTF-8"));

            // 4. Subject: 邮件主题
            message.setSubject(subject, "UTF-8");

            // 5. Content: 邮件正文（可以使用html标签）
            message.setContent(content, "text/html;charset=UTF-8");

            // 6. 设置发件时间
            message.setSentDate(new Date());

            // 7. 保存设置
            message.saveChanges();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return message;
    }

    /**
     * 创建一封只包含文本的简单邮件
     *
     * @param receiveMail 收件人邮箱
     * @param context     邮件内容
     */
    public static void sendMessage(EmailServerCfg cfg, String receiveMail, String context) throws Exception {

        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
        Session session = getSession(cfg);

        // 设置为debug模式, 可以查看详细的发送 log
        session.setDebug(true);

        // 3. 构建邮件
        MimeMessage message = buildMessage(cfg, session, receiveMail, "主题", context);

        // 4. 根据 Session 获取邮件传输对象
        Transport transport = session.getTransport();
        transport.connect(myEmailAccount, myEmailPassword);

        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        // 7. 关闭连接
        transport.close();
    }

    /**
     * 用于连接邮件服务器参数配置对象
     */
    @Data
    public static class EmailServerCfg {

        // 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
        public String host;

        // 是否启用ssl
        public Integer enableSsl;

        // 使用的协议（JavaMail规范要求）
        public String protocol;

        //端口
        public String port;

        //发送人邮箱账号
        public String account;

        //邮箱密码不是登录密码，需要登录邮箱后台配置
        public String password;
    }

    public static String generateRandomEmail() {
        String[] providers = {"@gmail.com",
            "@yahoo.com",
            "@outlook.com",
            "@icloud.com",
            "@hotmail.com",
            "@aol.com",
            "@zoho.com",
            "@protonmail.com",
            "@mail.com"};
        Random random = new Random();

        String username = generateRandomString(new Random().nextInt(8, 18));
        String provider = providers[random.nextInt(providers.length)];

        return username + provider;
    }

    private static String generateRandomString(int length) {
        String characters = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            char c = characters.charAt(random.nextInt(characters.length()));
            sb.append(c);
        }

        return sb.toString();
    }
}
